package com.bw.mvi.http

import android.os.Environment
import com.tencent.mmkv.MMKV
import com.zyj.retrofit.adapter.FlowCallAdapterFactory
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

/**
 * OkHttpClient管理类
 */
object OkHttpClientManager {
    /**
     * 普通的http请求客户端
     */
    val commonHttpClient : OkHttpClient by lazy {
        val okHttpClient = OkHttpClient.Builder().apply {
            callTimeout(Const.CONNECT_TIME_OUT,TimeUnit.SECONDS)
            readTimeout(Const.READ_TIME_OUT,TimeUnit.SECONDS)
            writeTimeout(Const.WRITE_TIME_OUT,TimeUnit.SECONDS)
            if(BuildConfig.isOpenLog){
                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            }
            addInterceptor(headerInterceptor())
            //服务器异常拦截器
            addInterceptor(getServiceExceptionInterceptor())
            //证书
            sslSocketFactory(sslSocketFactory,trustManner)
            //防止抓包
            proxy(Proxy.NO_PROXY)
        }
        okHttpClient.build()
    }
    fun createRetrofit(): Retrofit{
        return  Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .client(commonHttpClient)
            .addCallAdapterFactory(FlowCallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }
    /**
     * Interceptor 拦截器 使用责任链模式
     */
    private fun getServiceExceptionInterceptor(): Interceptor {
        return Interceptor { chain ->
            val response = chain.proceed(chain.request())
            val responseBuilder = response.newBuilder()
            if (response.code == 500){
                val newJson = JSONObject()
                newJson.put("code", 500)
                newJson.put("message", "服务器异常,请联系客服")
                responseBuilder.body(newJson.toString().toResponseBody("application/json".toMediaTypeOrNull()))
            }
            responseBuilder.build()
        }
    }
    private val sslSocketFactory: SSLSocketFactory
        get() = try {
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, arrayOf(), SecureRandom())
            sslContext.socketFactory
        }catch (e: Exception){
            throw RuntimeException(e)
        }
    private val trustManner : X509TrustManager
        get() = object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {

            }

            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {

            }

            override fun getAcceptedIssuers(): Array<X509Certificate> {
                return arrayOf()
            }

        }
    private fun headerInterceptor() : Interceptor {
        return Interceptor { chain ->
            val token = MMKV.defaultMMKV().decodeString(Const.TOKEN, "")
            val builder = chain.request().newBuilder()
            if (token != null) {
                builder.addHeader(Const.TOKEN,token)
            }
            //执行请求
            val response = chain.proceed(builder.build())
            //token过期
            if(response.code == 401||response.code == 403){
                //重新登录
//                ARouter.getInstance().build(RoutePath.LOGIN_ACTIVITY).navigation()
            }
            response
        }
    }
    /**
     * https请求客户端
     */
    val httpsClient : OkHttpClient by lazy {
        val okHttpClient = OkHttpClient.Builder().apply {
            callTimeout(Const.CONNECT_TIME_OUT,TimeUnit.SECONDS)
            readTimeout(Const.READ_TIME_OUT,TimeUnit.SECONDS)
            writeTimeout(Const.WRITE_TIME_OUT,TimeUnit.SECONDS)
            if(BuildConfig.isOpenLog){
                addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            }
            addInterceptor(headerInterceptor())
            //服务器异常拦截器
            addInterceptor(getServiceExceptionInterceptor())
            //证书
            sslSocketFactory(sslSocketFactory,trustManner)
            //支持http2
            protocols(listOf(Protocol.HTTP_2))
            val storageDirectory = getExternalStorageDirectory()
            if(storageDirectory!=null){
                cache(Cache(storageDirectory,10*1024*1024))
            }

            //防止抓包
            proxy(Proxy.NO_PROXY)
        }
        okHttpClient.build()
    }
    private val webSocketInstance : OkHttpClient by lazy {
        var wsOKBuilder = OkHttpClient.Builder().apply {
            pingInterval(10, TimeUnit.SECONDS)
        }
        wsOKBuilder.build()
    }
    /**
     * Retrofit实例
     */
    val retrofitInstance : Retrofit by lazy {
        Retrofit.Builder().apply {
            baseUrl(BuildConfig.BASE_URL)
            client(commonHttpClient)
            addConverterFactory(GsonConverterFactory.create())
        }.build()
    }
    val retrofitHttpsInstance : Retrofit by lazy {
        Retrofit.Builder().apply {
            baseUrl(BuildConfig.BASE_URL)
            client(httpsClient)
            addConverterFactory(GsonConverterFactory.create())
        }.build()
    }
    /**
     * 发起webSocket请求
     */
    fun createWebSocketRequest(webSocketUrl : String, listener : WebSocketListener){
        val requestBuilder = Request.Builder().apply {
            url(webSocketUrl)
        }
        webSocketInstance.newWebSocket(requestBuilder.build(),listener)

    }
    private fun getExternalStorageDirectory(): File? {
        val file = Environment.getExternalStorageDirectory()
        return if(file.exists()){
            val cacheFile = File(file.path,"okhttpCache")
            if(!cacheFile.exists()){
                cacheFile.mkdirs()
            }
            cacheFile
        }else{
            null
        }
    }
    fun clearAllRequest(){
        //关闭连接池
        commonHttpClient.dispatcher.executorService.shutdown()
        httpsClient.dispatcher.executorService.shutdown()
        webSocketInstance.dispatcher.executorService.shutdown()
        //关闭缓存
        commonHttpClient.cache?.close()
        httpsClient.cache?.close()
        webSocketInstance.cache?.close()
    }
}